<template>
	<view class="region-container">
		<view id="image-wrapper" class="image-wrapper"
			:style="{ width: displayWidth + 'px', height: displayHeight + 'px' }">
			<image class="scaled-image" :src="imgConfig.url"
				:style="{ width: displayWidth + 'px', height: displayHeight + 'px' }" mode="widthFix"
				@load="onImageLoad"></image>

			<!-- 多边形绘制层（使用view+clip-path） -->
			<view class="polygons-container">
				<view v-for="(line, index) in processedLines" :key="index" class="polygon-wrapper" :style="{
                        width: displayWidth + 'px',
                        height: displayHeight + 'px'
                    }">

					<!-- 填充层 -->
					<view class="polygon-fill" :style="{
                            clipPath: `polygon(${line.pointsString})`,
                            backgroundColor: line.fillStyle
                        }">
					</view>

					<!-- 边框线条 -->
					<view v-for="(edge, edgeIndex) in line.edges" :key="edgeIndex" class="polygon-edge" :style="{
                            left: edge.startX + 'px',
                            top: edge.startY + 'px',
                            width: edge.length + 'px',
                            height: edge.width + 'px',
                            backgroundColor: line.strokeColor,
                            transformOrigin: '0 50%',
                            transform: `rotate(${edge.angle}rad)`
                        }">
					</view>

					<!-- 极值边界框 -->
					<view v-if="false" class="extreme-bounds-wrapper" :style="{
                            left: line.bounds.xMin + 'px',
                            top: line.bounds.yMin + 'px',
                            width: (line.bounds.xMax - line.bounds.xMin) + 'px',
                            height: (line.bounds.yMax - line.bounds.yMin) + 'px'
                        }">
						<!-- 外层白色边框 -->
						<view class="extreme-bounds-outer"></view>
						<!-- 内层黑色边框 -->
						<view class="extreme-bounds-inner"></view>
					</view>

					<!-- 文本框容器 -->
					<view v-if="line.lineLabel.show" class="lineText"
						:style="`left:${line.bounds.leftScaled}px;top:${line.bounds.topScaled}px;font-size:${line.lineLabel.size}rpx;color:${line.lineLabel.color}`">
						<text>{{ line.lineLabel.text }}</text>
					</view>

				</view>
			</view>

			<!-- 标记点容器 -->
			<view v-if="processedMarkers.length" class="markers-container"
				:style="{ width: displayWidth + 'px', height: displayHeight + 'px' }">
				<view style="position: relative;">
					<view v-for="(marker, index) in processedMarkers" :key="marker.id || index" class="marker-item"
						:style="{
                                        left: marker.scaledX + 'px',
                                        top: marker.scaledY + 'px',
                                        transform: `translate(-50%, -50%)`
                                      }" @click="handleMarkerClick(marker)">
						<!-- 标记点图标 -->
						<view class="marker-icon-wrapper" :class="marker.className" style="z-index: 10;">
							<image v-if="!useUvLoadMarker" :style="`width: ${marker.size}px; height: ${marker.size}px;`" :src="marker.iconUrl || defaultMarkerIcon" :width="marker.size"
								:height="marker.size" class="marker-icon"
								:class="{'marker-active': selectedMarkerId === marker.id}">
							</image>
							<uv-image v-else :src="marker.iconUrl || defaultMarkerIcon" :width="marker.size"
								:height="marker.size" class="marker-icon"
								:class="{'marker-active': selectedMarkerId === marker.id}">
							</uv-image>
						</view>
					</view>
				</view>
			</view>
		</view>

		<!-- 独立的标签容器，层级高于标记点容器 -->
		<view v-if="selectedMarker && selectedMarker.labels" class="labels-overlay"
			:style="{ width: displayWidth + 'px', height: displayHeight + 'px' }">
			<!-- 标签占位元素，用于测量高度 -->
			<view ref="labelPlaceholder" class="marker-labels-wrapper placeholder" id="label-placeholder"
				data-ref="label-placeholder" :style="{ visibility: 'hidden', opacity: 1, transform: 'none' }">
				<view class="marker-labels">
					<view v-for="(label, idx) in selectedMarker.labels" :key="idx" class="label-text">
						{{ label }}
					</view>
				</view>
			</view>

			<!-- 实际显示的标签 -->
			<view ref="label-visable" class="marker-labels-wrapper" :style="{
                    left: (selectedMarker.scaledX - labelOffsetX) + 'px',
                    top: (selectedMarker.scaledY - labelOffsetY) + 'px'
                }" :class="{ 'active': selectedMarkerId }">
				<view id="visable-label" class="marker-labels">
					<view v-for="(label, idx) in selectedMarker.labels" :key="idx" class="label-text rm-nowrap">
						{{ label }}
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
	export default {
		props: {
			imgConfig: {
				type: Object,
				required: true,
				default: () => ({
					url: '', // 图片链接  必须
					width: undefined, // 图片原始宽度	必须
					height: undefined, //图片原始高度	必须
				})
			},
			markers: {
				type: Array,
				default: () => [{
					id: undefined, //图标唯一标识，不可相同  必须
					labels: [], //图标上方的标签 
					coorX: undefined, // 图标相对于图片的X轴 必须
					coorY: undefined, // 图标相对于图片的Y轴 必须
					size: 16, // 图标大小 默认16
					className: '', // 自定义类目
					iconUrl: '', // 图标路径          必须
				}]
			},
			lines: {
				type: Array,
				default: () => [{
					type: 'Polygon', // 线的类型 
					lineList: [{
							coorX: 0,
							coorY: 0
						}, // 线框坐标(多个)，起始点必须和结尾闭合形成闭环
					],
					style: {
						color: '#000', // 线的颜色 默认值 #000
						fillColor: undefined, // 填充颜色，如果是 undefined 则不填充。
						fillOpacity: 0 // 透明度 默认0
					},
					lineLabel: {
						text: undefined, //闭合线区域内的文本
						color: '#000', // 文本颜色 默认值 #000
						size: 16, // 文本大小 默认值16
						x: 50, // 默认居中  x和y需要是0-100范围
						y: 50, // 默认居中
						show: false // 是否展示，默认是false
					}
				}, ],
			},
			useUvLoadMarker: {
				type: Boolean,
				default: false
			},
		},

		watch: {
			imgConfig: {
				deep: true,
				handler() {
					this.selectedMarkerId = null
					this.calculateImageSize();
				}
			},
			lines: {
				deep: true,
				handler() {}
			},
			scaleRatio() {}
		},

		data() {
			return {
				displayWidth: 0, // 显示宽度
				displayHeight: 0, // 显示高度
				scaleRatio: 1, // 缩放比例
				defaultMarkerIcon: 'https://picsum.photos/30/30', // 默认标记图标
				selectedMarkerId: null, // 当前选中的标记点ID
				labelOffsetY: 0, // 标签y偏移量
				labelOffsetX: 0, // 标签的x偏移量
				calculateMarkersForm: {
					scaledX: 0,
					scaledY: 0,
					imageDistanceTop: 0,
				},
				// 当前选中的多边形ID
				selectedLineId: null,
			};
		},

		computed: {
			// 当前选中的标记点
			selectedMarker() {
				if (!this.selectedMarkerId) return null;
				return this.processedMarkers.find(marker => marker.id === this.selectedMarkerId) || null;
			},

			processedMarkers() {
				if (!this.markers || !this.markers.length || !this.scaleRatio) return [];

				return this.markers.map(marker => {
					const x = marker.coorX !== undefined ? marker.coorX : marker.x;
					const y = marker.coorY !== undefined ? marker.coorY : marker.y;
					const size = marker.size !== undefined ? marker.size :
						(marker.width || marker.height || 30);

					return {
						...marker,
						x,
						y,
						scaledX: x * this.scaleRatio,
						scaledY: y * this.scaleRatio,
						size: size
					};
				});
			},

			processedLines() {
				if (!this.lines || !this.lines.length || !this.scaleRatio) return [];

				return this.lines.map(line => {
					if (line.type !== 'Polygon' || !Array.isArray(line.lineList) || line.lineList.length < 3) {
						return null;
					}

					// 坐标转换
					const points = line.lineList.map(point => ({
						x: (point.coorX !== undefined ? point.coorX : point.x) * this.scaleRatio,
						y: (point.coorY !== undefined ? point.coorY : point.y) * this.scaleRatio
					}));

					// 生成clip-path坐标字符串
					const pointsString = points.map(p => `${p.x}px ${p.y}px`).join(', ');

					// 处理填充样式（带透明度）
					let fillStyle = 'transparent';
					if (line.style.fill && line.style.fillColor) {
						const hex = line.style.fillColor.replace('#', '');
						const r = parseInt(hex.substring(0, 2), 16);
						const g = parseInt(hex.substring(2, 4), 16);
						const b = parseInt(hex.substring(4, 6), 16);
						const opacity = line.style.fillOpacity || 1;
						fillStyle = `rgba(${r}, ${g}, ${b}, ${opacity})`;
					}

					// 处理描边样式
					const strokeColor = line.style.color || '#000';
					const strokeWidth = line.style.width || 1;

					// 计算多边形每条边的线条数据
					const edges = [];
					for (let i = 0; i < points.length - 1; i++) {
						edges.push(this.calculateEdge(points[i], points[i + 1], strokeWidth));
					}

					// 闭合多边形：最后一个点连接到第一个点
					if (points.length > 1) {
						edges.push(this.calculateEdge(points[points.length - 1], points[0], strokeWidth));
					}

					// 计算极值
					const xValues = points.map(point => point.x);
					const yValues = points.map(point => point.y);
					const xMin = Math.min(...xValues);
					const xMax = Math.max(...xValues);
					const yMin = Math.min(...yValues);
					const yMax = Math.max(...yValues);

					// 根据百分比计算文本位置
					// lineLabel.x 和 lineLabel.y 是0-100的百分比值
					const labelXPercent = line.lineLabel.x !== undefined ? line.lineLabel.x : 50; // 默认50%（居中）
					const labelYPercent = line.lineLabel.y !== undefined ? line.lineLabel.y : 50; // 默认50%（居中）

					// 将百分比转换为实际坐标 ,这里需要减去一个当前文本大小的左边偏移量，不然是以文本的左上角顶点的，我们需要以文本右下为顶点固定到极值的左上。
					//#ifdef MP-WEIXIN
					const leftScaled = xMin + (xMax - xMin) * (labelXPercent / 100) - line.lineLabel.size
					const topScaled = yMin + (yMax - yMin) * (labelYPercent / 100) - line.lineLabel.size + 10
					//#endif
					// 除了微信的其他
					//#ifndef MP-WEIXIN
					const leftScaled = xMin + (xMax - xMin) * (labelXPercent / 100) - line.lineLabel.size
					const topScaled = yMin + (yMax - yMin) * (labelYPercent / 100) - line.lineLabel.size + 10
					//#endif
					line.bounds = {
						xMin,
						xMax,
						yMin,
						yMax,
						leftScaled,
						topScaled
					};

					return {
						...line,
						pointsString,
						fillStyle,
						strokeColor,
						strokeWidth,
						edges,
					};
				}).filter(Boolean); // 过滤无效项
			}
		},

		mounted() {
			this.calculateImageSize();
		},

		methods: {
			// 根据编号展示对应标签
			showLabelByNumber(serialNumber) {
			  // 遍历markers
			  const matchedMarker = this.markers.find(item => {
				if (!item.labels || !Array.isArray(item.labels)) {
				  return false;
				}
				return item.labels.some(label => label.includes(serialNumber));
			  });
			  if (matchedMarker) {
				this.selectedMarkerId = matchedMarker.id; 
			  }
			},
			// 处理多边形点击事件 这个点击事件暂时用不了，不知道为啥？
			handleLineClick(line, event) {
				event.stopPropagation();
				// 如果点击的是当前选中的多边形，则取消选中；否则选中该多边形
				this.selectedLineId = this.selectedLineId === line.id ? null : line.id;
			},

			// 计算两个点之间的线条数据
			calculateEdge(point1, point2, width) {
				// 计算两点之间的距离
				const dx = point2.x - point1.x;
				const dy = point2.y - point1.y;
				const length = Math.sqrt(dx * dx + dy * dy);

				// 计算旋转角度（弧度）
				const angle = Math.atan2(dy, dx);

				return {
					startX: point1.x,
					startY: point1.y,
					length,
					width,
					angle
				};
			},

			// 计算图片显示尺寸以及距离顶部的距离
			calculateImageSize() {
				const {
					width,
					height
				} = this.imgConfig;
				if (!width || !height) return;

				const {
					windowWidth
				} = uni.getSystemInfoSync();
				const screenWidth = windowWidth;
				const expectedHeight = (height / width) * screenWidth;
				const maxHeight = uni.upx2px(500);

				this.displayWidth = screenWidth;
				this.displayHeight = Math.min(expectedHeight, maxHeight);
				this.scaleRatio = this.displayWidth / width;

				this.$emit('resize', {
					width: this.displayWidth,
					height: this.displayHeight,
					scaleRatio: this.scaleRatio
				});

				const imageWrapper = uni.createSelectorQuery().in(this).select('#image-wrapper');
				imageWrapper.boundingClientRect(data => {
					this.calculateMarkersForm.imageDistanceTop = data.top;
				}).exec();
			},

			// 图片加载完成事件
			onImageLoad(e) {
				this.$emit('imageLoad');
			},

			// 处理标记点点击事件
			handleMarkerClick(marker) {
				this.selectedMarkerId = this.selectedMarkerId === marker.id ? null : marker.id;
				// 得到当前点击的markers
				const currmentMarker = this.processedMarkers.filter(item => item.id === marker.id)[0];
				this.calculateMarkersForm.scaledX = currmentMarker.scaledX;
				this.calculateMarkersForm.scaledY = currmentMarker.scaledY;
				// 延迟计算标签高度，确保DOM已更新
				this.$nextTick(() => {
					this.updateLabelPosition();
				});
				this.$emit('markerClick', marker)
			},

			// 更新标签位置
			updateLabelPosition() {
				if (this.selectedMarkerId === null || !this.selectedMarkerId) return;
				// #ifdef H5
				if (!this.$refs.labelPlaceholder) return;
				// #endif
				let that = this;
				const visableLabel = uni.createSelectorQuery().in(this).select('#visable-label');

				visableLabel.boundingClientRect(data => {
					const rightResult = data.width / 2 + this.calculateMarkersForm.scaledX;
					const leftResult = this.calculateMarkersForm.scaledX - (data.width / 2);
					const topResult = data.height;
					if (rightResult > this.displayWidth) {
						that.labelOffsetX = Math.abs(this.displayWidth - rightResult);
					} else if (leftResult < 0) {
						that.labelOffsetX = -(Math.abs(leftResult) + 5);
					} else {
						that.labelOffsetX = 0;
					}

					if (topResult > this.calculateMarkersForm.scaledY) {
						that.labelOffsetY = -10;
					} else {
						that.labelOffsetY = data.height + 10;
					}
				}).exec();
			}
		}
	}
</script>

<style scoped>
	@import url("./rm-regionImg.css");
</style>